package com.kelw.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kelw.annotation.Cache;
import com.kelw.constatnt.UserConstants;
import com.kelw.exception.BusinessException;
import com.kelw.exception.CommonErrorCode;
import com.kelw.dto.AddUserDto;
import com.kelw.dto.LoginDto;
import com.kelw.dto.RegisterDto;
import com.kelw.dto.UpdateUserInfoDto;
import com.kelw.entity.User;
import com.kelw.mapper.UserMapper;
import com.kelw.service.UserService;
import com.kelw.utils.JwtUtils;
import com.kelw.utils.SaltEncryption;
import com.kelw.vo.PageResponse;
import com.kelw.vo.UserInfoVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.kelw.utils.CommonUtils.setLikeWrapper;
import static com.kelw.vo.UserInfoVo.fromUser;


@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private  UserMapper userMapper;

    @Resource
    private RedisTemplate<String,String> redisTemplate;


    @Override
    public String register(RegisterDto registerDto) {
        //判断用户账号是否已经注册过
        if (!checkPhone(registerDto.getPhone())) {
            throw new BusinessException(CommonErrorCode.E_100103);
        }
        // 盐值
        String salt = UUID.randomUUID().toString().substring(0, 6);
        //对密码进行加MD5加密
        String newPwd = SaltEncryption.saltEncryption(registerDto.getPassword(), salt);
        // 判断手机验证码和输入的验证码是否一致
        String redisCode = redisTemplate.opsForValue().get(registerDto.getPhone());
        if(!registerDto.getCode().equals(redisCode)) {
            throw new BusinessException(CommonErrorCode.E_100104);
        }
        User user = new User();
        BeanUtils.copyProperties(registerDto, user);
        user.setPassword(newPwd);
        user.setSalt(salt);
        //设置注册者的权限为学生级别，教师和管理员级别由管理员操作
        user.setRoleId(UserConstants.USER_ROLE);
        user.setCreateDate(new Date());

        userMapper.insert(user);
        // 发放token令牌
        return JwtUtils.createToken(user);
    }

    @Override
    public Boolean checkPhone(String phone) {
        return userMapper.selectCount(new QueryWrapper<User>().eq("phone", phone))  < 1;
    }

    @Override
    public String login(LoginDto loginDto) {
        //判断该手机号是否已经注册
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("phone", loginDto.getPhone()));
        Integer roleId = user.getRoleId();
        if (user == null) {
            throw new BusinessException(CommonErrorCode.E_100102);
        }
        String saltPassword = SaltEncryption.saltEncryption(loginDto.getPassword(), user.getSalt());
        //判断用户密码是否正确
        if (!saltPassword.equals(user.getPassword()) && user.getStatus() == 1) {
            throw new BusinessException(CommonErrorCode.E_100101);
        }
        //判断用户是否被封禁
        if(user.getStatus() == 1){
            throw new BusinessException(CommonErrorCode.E_100107);
        }
        String result = JwtUtils.createToken(user);
        // 发放token令牌
        return result;
    }

    @Override
    @Cache(prefix = "user", suffix = "#username", ttl = 10, randomTime = 2, timeUnit = TimeUnit.HOURS)
    public User getUserByUsername(String username) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("username", username));
    }

    @Override
    @Cache(prefix = "user", suffix = "#updateUserInfoDto.getUsername()", ttl = 10, randomTime = 2, timeUnit = TimeUnit.HOURS, resetCache = true)
    public User updateUserInfo(UpdateUserInfoDto updateUserInfoDto) {
        User user = getUserByUsername(updateUserInfoDto.getUsername());
        user.updateFrom(updateUserInfoDto);
        userMapper.updateById(user);
        return user;
    }

    @Override
    public PageResponse<UserInfoVo> getUser(String phone, String trueName, Integer pageNo, Integer pageSize) {
        IPage<User> userPage = new Page<>(pageNo, pageSize);

        Map<String, Object> queryParams = new HashMap<>();
        queryParams.put("phone", phone);
        queryParams.put("true_name", trueName);

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        setLikeWrapper(wrapper, queryParams);
        wrapper.orderByDesc("role_id", "create_date");
        wrapper.orderByAsc("status");

        userPage = userMapper.selectPage(userPage, wrapper);
        List<UserInfoVo> records = userPage.getRecords().stream().map(UserInfoVo::fromUser).collect(Collectors.toList());

        return PageResponse.<UserInfoVo>builder().data(records).total(userPage.getTotal()).build();
    }

    @Override
    public void handlerUser(Integer type, String userIds) {
        // 转换成数组 需要操作的用户的id数组
        String[] ids = userIds.split(",");
        switch (type) {
            case 1:
                updateUserStatus(ids, 1);
                break;
            case 2:
                updateUserStatus(ids, 2);
                break;
            case 3:
                for (String id : ids) {
                    userMapper.deleteById(Integer.parseInt(id));
                }
                break;
            default:
                throw new BusinessException(CommonErrorCode.E_100105);
        }
    }

    @Override
    public void addUser(AddUserDto addUserDto) {
        // 盐值
        String salt = UUID.randomUUID().toString().substring(0, 6);
        String newPwd = SaltEncryption.saltEncryption(addUserDto.getPassword(), salt);
        User user = addUserDto.toUser();
        user.setPassword(newPwd);
        user.setSalt(salt);
        user.setCreateDate(new Date());
        userMapper.insert(user);
    }

    @Override
    public UserInfoVo getUserInfoById(Integer userId) {
        return fromUser(userMapper.selectById(userId));
    }

    @Override
    public List<UserInfoVo> getUserInfoByIds(List<Integer> userIds) {
        return userMapper.selectBatchIds(userIds).stream()
                .map(UserInfoVo::fromUser)
                .collect(Collectors.toList());
    }

    @Override
    public PageResponse<UserInfoVo> getDoctor(Integer officeId, String trueName, Integer pageNo, Integer pageSize) {
        IPage<User> userPage = new Page<>(pageNo, pageSize);

        Map<String, Object> queryParams = new HashMap<>();
        queryParams.put("office_id", officeId);
        queryParams.put("true_name", trueName);

        QueryWrapper<User> wrapper = new QueryWrapper<>();
        setLikeWrapper(wrapper, queryParams);
        wrapper.eq("role_id",2);
        wrapper.orderByDesc("role_id", "create_date");
        wrapper.orderByAsc("status");

        userPage = userMapper.selectPage(userPage, wrapper);
        List<UserInfoVo> records = userPage.getRecords().stream().map(UserInfoVo::fromUser).collect(Collectors.toList());

        return PageResponse.<UserInfoVo>builder().data(records).total(userPage.getTotal()).build();
    }

    private void updateUserStatus(String[] ids, Integer status) {
        for (String id : ids) {
            // 当前需要修改的用户
            User user = userMapper.selectById(Integer.parseInt(id));
            user.setStatus(status);// 设置为启用的用户
            userMapper.updateById(user);
        }
    }
}
